package com.zycfc.zsf.boot.util.number;

import java.util.*;
import java.util.concurrent.*;
import java.security.*;
import com.zycfc.zsf.boot.util.bean.*;
import org.apache.commons.lang3.*;

public abstract class RandomUtils
{
    public static Random threadLocalRandom() {
        return ThreadLocalRandom.current();
    }
    
    public static SecureRandom secureRandom() {
        try {
            return SecureRandom.getInstance("SHA1PRNG");
        }
        catch (NoSuchAlgorithmException e) {
            return new SecureRandom();
        }
    }
    
    public static int nextInt() {
        return nextInt(threadLocalRandom());
    }
    
    public static int nextInt(final Random random) {
        int n = random.nextInt();
        if (n == Integer.MIN_VALUE) {
            n = 0;
        }
        else {
            n = Math.abs(n);
        }
        return n;
    }
    
    public static int nextInt(final int max) {
        return nextInt(threadLocalRandom(), max);
    }
    
    public static int nextInt(final Random random, final int max) {
        return random.nextInt(max);
    }
    
    public static int nextInt(final int min, final int max) {
        return nextInt(threadLocalRandom(), min, max);
    }
    
    public static int nextInt(final Random random, final int min, final int max) {
        Validate.isTrue(max >= min, "Start value must be smaller or equal to end value.", new Object[0]);
        ValidateMore.nonNegative("min", min);
        if (min == max) {
            return min;
        }
        return min + random.nextInt(max - min);
    }
    
    public static long nextLong() {
        return nextLong(threadLocalRandom());
    }
    
    public static long nextLong(final Random random) {
        long n = random.nextLong();
        if (n == Long.MIN_VALUE) {
            n = 0L;
        }
        else {
            n = Math.abs(n);
        }
        return n;
    }
    
    public static long nextLong(final long max) {
        return nextLong(threadLocalRandom(), 0L, max);
    }
    
    public static long nextLong(final Random random, final long max) {
        return nextLong(random, 0L, max);
    }
    
    public static long nextLong(final long min, final long max) {
        return nextLong(threadLocalRandom(), min, max);
    }
    
    public static long nextLong(final Random random, final long min, final long max) {
        Validate.isTrue(max >= min, "Start value must be smaller or equal to end value.", new Object[0]);
        ValidateMore.nonNegative("min", min);
        if (min == max) {
            return min;
        }
        return (long)(min + (max - min) * random.nextDouble());
    }
    
    public static double nextDouble() {
        return nextDouble(threadLocalRandom(), 0.0, Double.MAX_VALUE);
    }
    
    public static double nextDouble(final Random random) {
        return nextDouble(random, 0.0, Double.MAX_VALUE);
    }
    
    public static double nextDouble(final double max) {
        return nextDouble(threadLocalRandom(), 0.0, max);
    }
    
    public static double nextDouble(final Random random, final double max) {
        return nextDouble(random, 0.0, max);
    }
    
    public static double nextDouble(final double min, final double max) {
        return nextDouble(threadLocalRandom(), min, max);
    }
    
    public static double nextDouble(final Random random, final double min, final double max) {
        Validate.isTrue(max >= min, "Start value must be smaller or equal to end value.", new Object[0]);
        ValidateMore.nonNegative("min", min);
        return min + (max - min) * random.nextDouble();
    }
    
    public static String randomStringFixLength(final int length) {
        return RandomStringUtils.random(length, 0, 0, true, true, (char[])null, threadLocalRandom());
    }
    
    public static String randomStringFixLength(final Random random, final int length) {
        return RandomStringUtils.random(length, 0, 0, true, true, (char[])null, random);
    }
    
    public static String randomStringRandomLength(final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, true, (char[])null, threadLocalRandom());
    }
    
    public static String randomStringRandomLength(final Random random, final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(random, minLength, maxLength), 0, 0, true, true, (char[])null, random);
    }
    
    public static String randomLetterFixLength(final int length) {
        return RandomStringUtils.random(length, 0, 0, true, false, (char[])null, threadLocalRandom());
    }
    
    public static String randomLetterFixLength(final Random random, final int length) {
        return RandomStringUtils.random(length, 0, 0, true, false, (char[])null, random);
    }
    
    public static String randomLetterRandomLength(final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, false, (char[])null, threadLocalRandom());
    }
    
    public static String randomLetterRandomLength(final Random random, final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(random, minLength, maxLength), 0, 0, true, false, (char[])null, random);
    }
    
    public static String randomAsciiFixLength(final int length) {
        return RandomStringUtils.random(length, 32, 127, false, false, (char[])null, threadLocalRandom());
    }
    
    public static String randomAsciiFixLength(final Random random, final int length) {
        return RandomStringUtils.random(length, 32, 127, false, false, (char[])null, random);
    }
    
    public static String randomAsciiRandomLength(final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(minLength, maxLength), 32, 127, false, false, (char[])null, threadLocalRandom());
    }
    
    public static String randomAsciiRandomLength(final Random random, final int minLength, final int maxLength) {
        return RandomStringUtils.random(nextInt(random, minLength, maxLength), 32, 127, false, false, (char[])null, random);
    }
}
